package com.jt.www.queue.listen;

import com.jt.www.biz.pay.service.PayOutService;
import com.jt.www.dao.mapper.issue.mapper.IssuePolicyLogEntityMapper;
import com.jt.www.dao.mapper.issue.mapper.IssueRecordEntityMapper;
import com.jt.www.dao.mapper.issue.mapper.MqMessageEntityMapper;
import com.jt.www.dao.mapper.woxuebao.PayUrlInfoMapper;
import com.jt.www.enums.issue.IssueEnum;
import com.jt.www.enums.issue.PolicyEnum;
import com.jt.www.enums.woxuebao.PayOutStatusEnum;
import com.jt.www.message.JsonRootBean;
import com.jt.www.message.TbInsuranceSchema;
import com.jt.www.message.TbPolicyDtoList;
import com.jt.www.message.XmlHead;
import com.jt.www.model.issue.entity.IssuePolicyLogEntity;
import com.jt.www.model.issue.entity.IssueRecordEntity;
import com.jt.www.model.issue.entity.MqMessageEntity;
import com.jt.www.model.pay.ResBindDetailQo;
import com.jt.www.model.pay.ResBindQo;
import com.jt.www.model.reps.GenericListResponse;
import com.jt.www.model.woxuebao.PayOutEntity;
import com.jt.www.model.woxuebao.PayUrlInfoEntity;
import com.jt.www.queue.systemparametes.ConfigurationParameters;
import com.jt.www.remote.DexClient;
import com.jt.www.remote.ins.InsClient;
import com.jt.www.util.*;
import com.rabbitmq.client.Channel;
import org.apache.commons.lang.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import tk.mybatis.mapper.weekend.Weekend;
import tk.mybatis.mapper.weekend.WeekendCriteria;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

@Component
public class PayUrlListener {

    public static final Logger log = LoggerFactory.getLogger(PayUrlListener.class);
    @Autowired
    private MqMessageEntityMapper mqMessageEntityMapper;
    @Autowired
    private PayUrlInfoMapper payUrlInfoMapper;
    @Autowired
    private IssueRecordEntityMapper issueRecordEntityMapper;

//    @Autowired
//    private PayOutEntityMapper payOutEntityMapper;
    @Autowired
    private IssuePolicyLogEntityMapper issuePolicyLogEntityMapper;

//    @Autowired
//    private PayOutEntityMapper payOutEntityMapper;

    @Autowired
    private InsClient insClient;

    @Autowired
    private DexClient dexClient;

    @Autowired
    private PayOutService payOutService;

    //济南学平支付地址请求头
    @Value("${jtpf.jinanxueping.payUrl}")
    private String jnPayUrl;

    //serverName 保险公司提供,需base64加密
    @Value("${jtpf.jinanxueping.serverName}")
    private String serverName;

    //requestMethod 保险公司提供,需base64加密
    @Value("${jtpf.jinanxueping.requestMethod}")
    private String requestMethod;

    //Sysflag 保险公司提供,需base64加密
    @Value("${jtpf.jinanxueping.sysflag}")
    private String sysflag;

    //transCode 保险公司提供,需base64加密
    @Value("${jtpf.jinanxueping.transcode}")
    private String transcode;

    //payType 固定值 保险公司提供,需base64加密
    @Value("${jtpf.jinanxueping.payType}")
    private String payType;

    //sendName 固定值 保险公司提供,需base64加密
    @Value("${jtpf.jinanxueping.sendName}")
    private String sendName;

    //sendPwd 固定值 保险公司提供,需base64加密
    @Value("${jtpf.jinanxueping.sendPwd}")
    private String sendPwd;

    //operateType 固定值 保险公司提供,需base64加密
    @Value("${jtpf.jinanxueping.operateType}")
    private String operateType;

    //orderType 固定值 保险公司提供,需base64加密
    @Value("${jtpf.jinanxueping.orderType}")
    private String orderType;

    //modeFlag 固定值 保险公司提供,需base64加密
    @Value("${jtpf.jinanxueping.modeFlag}")
    private String modeFlag;

    //诚泰我学保支付地址
    @Value("${jtpf.chengtai.wxbPayUrl}")
    private String wxbPayUrl;

    private static final String PAY_URL_LISTENER_KEY = "PAY_URL_LISTENER_KEY";

    @Autowired
    private ConfigurationParameters configurationParameters;

    @RabbitListener(queues ="${jtpf.rabbit.queuename.payurl}")
    public void processMsg(Message msg, Channel channel) {

        String findCode = "PayUrlListener_" + System.currentTimeMillis();
        //现在使用序列号判断
        String serialNo = (String) msg.getMessageProperties().getHeaders().get("SerialNo");
        //幂等校验 判断当前消息是否已经执行(支付这块可以使用序列号，其他的消息根据情况来判断)
        //超时时间暂时设置成10秒
        if (StringUtils.isNotBlank(serialNo) &&
                !RedisUtil.setLock(RedisUtil.createLockKey(PAY_URL_LISTENER_KEY, serialNo), "1", 10L)){
            basicAck(findCode, msg, channel);
            return;
        }
        log.info("{}:PayUrlListener get MessageProperties  {}", findCode, msg.getMessageProperties().toString());
        log.info("{}:PayUrlListener get MessageBody  {}", findCode, new String(msg.getBody()));
        try {
            byte[] msgbody = msg.getBody();
            if (msgbody == null || msgbody.length == 0) {
                log.info("{}:返回报文为空 {} {}", findCode, msg.getMessageProperties().getReceivedExchange(), msg.getMessageProperties().getReceivedRoutingKey());
                return;
            }
            // 字节数组转换为输入流
            InputStream is = new ByteArrayInputStream(msgbody);
            // 解析xml
            SAXReader reader = new SAXReader();
            Document document = reader.read(is);
            Element rootElement = document.getRootElement();
            String ifCode = (String)msg.getMessageProperties().getHeaders().get("IfCode");
            if(StringUtils.isBlank(ifCode)){
                log.info("{} ifCode为空!", findCode);
                return;
            }
            //添加消息记录入库 并直接返回 ack
            MqMessageEntity mqMessageEntity = new MqMessageEntity();
            mqMessageEntity.setIfCode(ifCode);
            mqMessageEntity.setMessage(rootElement.asXML());
            mqMessageEntity.setCreateTime(new Date());
            mqMessageEntityMapper.insert(mqMessageEntity);
            processMqMessage(rootElement, ifCode, findCode);
        } catch (Exception ex) {
            ex.printStackTrace();
            log.error("{}:出错，出错信息为", findCode, ex);
        } finally {
            basicAck(findCode, msg, channel);
        }
    }

    private void basicAck(String findCode, Message msg, Channel channel){
        try {
            channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
        } catch (IOException e) {
            log.error("{}:ACK确认出错，出错信息为", findCode, e);
        }
    }

    /**
     * 处理消息
     * @param rootElement
     * @param logId
     */
    public void processMqMessage(Element rootElement,  String ifCode, String logId) throws Exception {

        log.info("{}:解析的消息：{}", logId, rootElement.asXML());

        // 保险公司响应的报文
        boolean result = true;
        switch (ifCode) {
            // 云南学平险获取支付地址
            case "20200312001":
            //济南学平获取支付地址
            case "202007221132250":
            //临沂见费出单
            case "202008201400250":
            //河南学平险获取支付地址
            case "202008271510580":
              //诚泰云南学平获取支付地址
            case "202101251532220":
                result = processPayUrl(rootElement, ifCode);
                break;
            // 云南学平险回调
            case "20200312002":
                //济南学平出单回调接口,后续下载电子保单
            case "202007231708310":
                //河南学平获取出单回调接口
            case "202008271514410":
                //诚泰我学保出单回调接口
            case "202101201139110":
                result = processPayResult(rootElement, ifCode);
                break;
            default:
                log.error("{}:错误的ifCode {}", logId, ifCode);
        }
        if (!result) {
            //消息入库定时重试5次
        }
    }

    /*
    *  只获取支付地址保存,不做任何逻辑操作,通用
     * @Author xq.wu
     * @Date 14:23 2020/9/1
     * @Param [rootElement, ifCode]
     * @return java.lang.Boolean
     **/
    private Boolean processPayUrl(Element rootElement, String ifCode) {

        String findCode = "processPayUrl_" + System.currentTimeMillis();

        try {
            String responseCode = XmlUtils.getStringValue(rootElement,"ResponseCode");
            String responseMessage = XmlUtils.getStringValue(rootElement,"ResponseMessage");
            // 投保单号
            String tbNo = XmlUtils.getStringValue(rootElement, "ApplicationFormCode");
            // 投保人名称
            String holderName = XmlUtils.getStringValue(rootElement, "HolderName");
            // 投保人编号
            String holderCode = XmlUtils.getStringValue(rootElement, "HolderCode");
            // 投保人证件类型
            String licenseType = XmlUtils.getStringValue(rootElement, "LicenseType");
            // 投保人证件号码
            String licenseNo = XmlUtils.getStringValue(rootElement, "LicenseNo");
            // 平安投保单号
            String applyPolicyNo = XmlUtils.getStringValue(rootElement, "ApplyPolicyNo");
            // 平安cpc通知单号
            String cpcNoticeNo = XmlUtils.getStringValue(rootElement, "CpcNoticeNo");
            // 投保时间
            String startDate = XmlUtils.getStringValue(rootElement, "StartDate");
            // 起期
            String polStartDate = XmlUtils.getStringValue(rootElement, "PolStartDate");
            // 止期
            String polEndDate = XmlUtils.getStringValue(rootElement, "PolEndDate");
            // 新保续保标识
            String renewal = XmlUtils.getStringValue(rootElement, "Renewal");
            String payUrl;
            // 支付地址
            if (ifCode.equals(IssueEnum.CODE_32.getIfCode())) {
                String amount = XmlUtils.getStringValue(rootElement, "Amount");
                //济南学平支付地址需要自己拼接
                payUrl = splicingJnPay(jnPayUrl, applyPolicyNo, serverName, requestMethod, sysflag, transcode, payType, amount);
            }else if(ifCode.equals(IssueEnum.CODE_47.getIfCode())) {
                //http://183.224.42.121:9999/echannel/chac/YeePay?orderCoder=01019210126134020&payAmt=100.00&payType=4&vhlType=0&combinationNo =D2101261535091657033
                payUrl = wxbPayUrl;
            }else{
                payUrl =XmlUtils.getStringValue(rootElement,"PayUrl");
            }
            //通过ifCode得到产品编号
            String proCode = IssueEnum.getProCodeByIfCode(ifCode);

            log.info("{} responseCode:{},responseMessage:{},tbNo:{} 处理开始", findCode, responseCode, responseMessage, tbNo);

            PayUrlInfoEntity entity = new PayUrlInfoEntity();
            entity.setApplicationFormCode(tbNo);
            entity.setHolderCode(holderCode);
            entity.setHolderName(holderName);
            entity.setLicenseNo(licenseNo);
            entity.setLicenseType(licenseType);
            entity.setApplyPolicyNo(applyPolicyNo);
            entity.setCpcNoticeNo(cpcNoticeNo);
            entity.setPayUrl(payUrl);
            entity.setApplicationDate(startDate);
            entity.setPolStartDate(polStartDate);
            entity.setPolEndDate(polEndDate);
            entity.setPayUrlMessage(responseMessage);
            entity.setPayStatus(false);// 支付状态 默认支付未成功
            entity.setIsDeleted(false);
            entity.setProCode(proCode);
            entity.setCreateTime(DateUtils.getCurrentTime());
            entity.setIssueTimes(0);
            if ("0000".equals(responseCode) || "SUCCESS".equals(responseCode)) {
                entity.setPayUrlStatus(true);
                entity.setIssueStatus("1");
                //插入payout
                PayOutEntity payOutEntity = createPayOutEntity(entity, renewal);
                log.info("{} tbNo:{} payUrl:{} 保存到支付超时检查表", findCode, tbNo, payUrl);
                payOutService.savePayOut(payOutEntity);
            } else {
                entity.setPayUrlStatus(false);
                entity.setIssueStatus("3");
                log.info("{} tbNo:{},payUrl:{},payUrlMessage:{}", findCode, tbNo, "未获取到该投保单支付地址", responseMessage);
            }

            payUrlInfoMapper.insertSelective(entity);

            return true;
        } catch (Exception e){
            e.printStackTrace();
        }
        return false;
    }

    private PayOutEntity createPayOutEntity(PayUrlInfoEntity payUrlInfoEntity, String renewal) {
        PayOutEntity payOutEntity = new PayOutEntity();
        payOutEntity.setApplicationFormCode(payUrlInfoEntity.getApplicationFormCode());
        payOutEntity.setHolderCode(payUrlInfoEntity.getHolderCode());
        payOutEntity.setProductCode(payUrlInfoEntity.getProCode());
        payOutEntity.setStartTime(new Date());
        payOutEntity.setStatus(PayOutStatusEnum.DEFAULT.getCode());
        payOutEntity.setIsRenewal(renewal);
        payOutEntity.setCreateTime(new Date());
        return payOutEntity;
    }

    /*
    *  拼接济南学平支付地址
     * @Author xq.wu
     * @Date 15:03 2020/7/24
     * @Param [payUrl, applyPolicyNo, serverName, requestMethod, Sysflag, transCode, payType, amount]
     * @return java.lang.String
     **/
    public static String splicingJnPay(String payUrl,String applyPolicyNo,String serverName,String requestMethod,String Sysflag,String transCode,String payType,String amount) throws  Exception{
        String serverNameBase =  Base64Util.encode(serverName,null);
        String  requestMethodBase =  Base64Util.encode(requestMethod,null);
        String  SysflagBase =  Base64Util.encode(Sysflag,null);
        String  transCodeBase =   Base64Util.encode(transCode,null);
        String  payTypeBase = Base64Util.encode(payType,null);
        String  applyPolicyNoBase = Base64Util.encode(applyPolicyNo,null);
        String  amountBase = Base64Util.encode(amount,null);
        String jnPay = payUrl + "?serverName=" + serverNameBase + "&requestMethod=" + requestMethodBase +"&proposalNo=" +applyPolicyNoBase + "&sysflag=" + SysflagBase + "&transCode=" +transCodeBase + "&sumPremium=" + amountBase +"&pageFlag="+ "&payType=" +payTypeBase ;
        return jnPay;
    }
    /*
    *  拼接济南学平电子保单入参
     * @Author xq.wu
     * @Date 15:58 2020/7/24
     * @Param [policyNo, holderIdNo, holderName]
     * @return java.lang.String
     **/
    public String jnPolicyMessage(String policyNo,String holderName,String holderIdNo){
        String sendSeq = Long.toString(Math.abs(new Random().nextLong()));
        JsonRootBean jsonRootBean = new JsonRootBean();
        XmlHead xmlHead = new XmlHead();
        xmlHead.setSendName(sendName);
        xmlHead.setSendPwd(sendPwd);
        xmlHead.setSendSeq(sendSeq);
        xmlHead.setSendTime(new Date());
        xmlHead.setSysFlag(sysflag);
        xmlHead.setOperateType(operateType);
        xmlHead.setModeFlag(modeFlag);
        xmlHead.setTransCode(transcode);
        xmlHead.setOrderType(orderType);
        List tbPolicyDtoList = new ArrayList();
        TbPolicyDtoList tbPolicyDto= new TbPolicyDtoList();
        TbInsuranceSchema tbInsuranceSchema = new TbInsuranceSchema();
        tbInsuranceSchema.setHolderIdNo(holderIdNo); //投保人证件号
        tbInsuranceSchema.setHolderName(holderName); //投保人名称
        tbInsuranceSchema.setPolicyNo(policyNo); //保单号
        tbPolicyDto.setTbInsuranceSchema(tbInsuranceSchema);
        tbPolicyDtoList.add(tbPolicyDto);
        jsonRootBean.setXmlHead(xmlHead);
        jsonRootBean.setTbPolicyDtoList(tbPolicyDtoList);
        String policyMessage =JsonUtils.toJson(jsonRootBean);
        log.info("济南学平拼接的电子保单入参{}" ,policyMessage);
        return policyMessage;
    }


    public String getPolicyUrl(String partnerCode,String policyUrl){
        return configurationParameters.getChengtaiPolicy()+partnerCode+"/policyNO/"+policyUrl;
    }
    private Boolean processPayResult(Element rootElement, String ifCode){

        String findCode = "processPayResult_"+System.currentTimeMillis();

        try{
            String responseCode = XmlUtils.getStringValue(rootElement,"ResponseCode");
            String responseMessage =XmlUtils.getStringValue(rootElement,"ResponseMessage");
            String cpcNoticeNo = XmlUtils.getStringValue(rootElement,"CpcNoticeNo");
            String bussinessNo = XmlUtils.getStringValue(rootElement,"BussinessNo");
            String cpcPayTime = XmlUtils.getStringValue(rootElement,"CpcPayTime");
            String policyNo = XmlUtils.getStringValue(rootElement,"PolicyNo");

            log.info("{} 返回结果 responseCode:{},responseMessage:{},cpcNoticeNo:{},bussinessNo:{},policyNo:{}",
                    findCode,responseCode,responseMessage,cpcNoticeNo,bussinessNo,policyNo);

            // 支付成功
            if("SUCCESS".equals(responseCode)){
                if(StringUtils.isNotBlank(policyNo)){
                    PayUrlInfoEntity entity = new PayUrlInfoEntity();
                    entity.setPayStatus(true);
                    entity.setPayMessage(responseMessage);
                    entity.setPolicyNo(policyNo);
                    entity.setBusinessNo(bussinessNo);
                    entity.setCpcPayTime(cpcPayTime);
                    entity.setUpdateTime(DateUtils.getCurrentTime());
                    entity.setIssueStatus("2");//出单成功

                    Weekend<PayUrlInfoEntity> weekend = Weekend.of(PayUrlInfoEntity.class);
                    WeekendCriteria<PayUrlInfoEntity,Object> criteria = weekend.weekendCriteria();
                    criteria.andEqualTo(PayUrlInfoEntity::getCpcNoticeNo, cpcNoticeNo);
                    payUrlInfoMapper.updateByExampleSelective(entity, weekend);

                    log.info("{} 更新t_pay_url_info表 成功", findCode);
                    // 查询payUrlInfo记录
                    List<PayUrlInfoEntity> list = payUrlInfoMapper.selectByExample(weekend);
                    if(list != null && list.size() > 0){
                        String appCode = list.get(0).getApplicationFormCode();
                        String proCode = IssueEnum.getProCodeByIfCode(ifCode);
                        // 保存保单号到t_issue_record表
                        IssueRecordEntity issueRecordEntity = new IssueRecordEntity();
                        issueRecordEntity.setApplicationFormCode(appCode);
                        List<IssueRecordEntity> select = issueRecordEntityMapper.select(issueRecordEntity);
                        issueRecordEntity.setProCode(proCode);
                        issueRecordEntity.setReqPacket(null);
                        issueRecordEntity.setPolicyNo(policyNo);
                        issueRecordEntity.setResPacket(rootElement.asXML());
                        issueRecordEntity.setSendStatus("2");
                        issueRecordEntity.setStatus("2");
                        issueRecordEntity.setCreateTime(DateUtils.getCurrentTime());
                        issueRecordEntity.setUpdateTime(DateUtils.getCurrentTime());
                        issueRecordEntity.setIfCode(ifCode);
                        if (ifCode.equals(IssueEnum.CODE_33.getIfCode())) {
                            issueRecordEntity.setCompanyCode("0001300041.00024");
                        } else if (ifCode.equals(IssueEnum.CODE_42.getIfCode())) {
                            issueRecordEntity.setCompanyCode("0001300053.00361");
                        } else if(ifCode.equals(IssueEnum.CODE_46.getIfCode())){
                            issueRecordEntity.setCompanyCode("0001300063.00002");
                        }else {
                            issueRecordEntity.setCompanyCode("0001300052.00541");
                        }
                        if (select != null && select.size() > 0) {
                            issueRecordEntity.setId(select.get(0).getId());
                            issueRecordEntityMapper.updateByPrimaryKeySelective(issueRecordEntity);
                            log.info("{} t_issue_record表更新记录完成 tbNo:{}", findCode, appCode);
                        }else{
                            issueRecordEntityMapper.insertSelective(issueRecordEntity);
                            log.info("{} t_issue_record表插入记录完成 tbNo:{}", findCode, appCode);
                        }

                        IssuePolicyLogEntity issuePolicyLogEntity = new IssuePolicyLogEntity();
                        String consumeStatus = "1";
                        issuePolicyLogEntity.setApplicationFormCode(list.get(0).getApplicationFormCode());
                        issuePolicyLogEntity.setPolicyNo(policyNo);
                        issuePolicyLogEntity.setType("1");//电子保单
                        issuePolicyLogEntity.setStatus(consumeStatus);
                        issuePolicyLogEntity.setCreateTime(DateUtils.getCurrentTime());
                        issuePolicyLogEntity.setUpdateTime(DateUtils.getCurrentTime());
                        issuePolicyLogEntity.setProCode(proCode);
                        String param = "";
                        if(ifCode.equals(IssueEnum.CODE_33.getIfCode())){
                            param = jnPolicyMessage(policyNo,list.get(0).getHolderName(),list.get(0).getLicenseNo());
                        }else if(ifCode.equals(IssueEnum.CODE_70.getIfCode())){
                            // 济南学平险下载电子保单 组装报文  组装json 报文
                            Map<String, String> map = new HashMap<>();
                            map.put("partnerName", "P_JTJJKM_PE");
                            map.put("productClass", "03");
                            map.put("requestId", "StandardElectronicPolicyV2"+System.currentTimeMillis());
                            map.put("departmentCode", "21685");
                            map.put("name", list.get(0).getHolderName());
                            map.put("policyNo", policyNo);
                            map.put("certificateNo", list.get(0).getLicenseNo());
                            if("cardType_0".equals(list.get(0).getLicenseType())){
                                map.put("certificateType", "01");
                            }else if("cardType_1".equals(list.get(0).getLicenseType())){
                                map.put("certificateType", "02");
                            }else if("cardType_17".equals(list.get(0).getLicenseType())){
                                map.put("certificateType", "05");
                            }
                             param = JsonUtils.toJson(map);
                        }else if(ifCode.equals(IssueEnum.CODE_46.getIfCode())){
                            //云南学平直接取电子保单地址
                            String policyUrl = getPolicyUrl(configurationParameters.getPartnerCode(),XmlUtils.getStringValue(rootElement,"policyUrl"));
                            // 拼装下载报文
                            Document doc = DocumentHelper.createDocument();
                            Element info = doc.addElement("Body");
                            info.addElement("url").addText(policyUrl);
                            param = info.asXML();
                        }else{
                            //河南学平直接取电子保单地址
                            String policyUrl  = XmlUtils.getStringValue(rootElement,"policyUrl");
                            // 拼装下载报文
                            Document doc = DocumentHelper.createDocument();
                            Element info = doc.addElement("Body");
                            info.addElement("url").addText(policyUrl);
                            param = info.asXML();
                        }

                        issuePolicyLogEntity.setParam(param);
                        issuePolicyLogEntity.setIfCode(ifCode);

                        //判断是否已经存在该投保单电子保单记录
                        Weekend<IssuePolicyLogEntity> issuePolicyLogWeekend = Weekend.of(IssuePolicyLogEntity.class);
                        WeekendCriteria<IssuePolicyLogEntity,Object> issuePolicyLogCriteria = issuePolicyLogWeekend.weekendCriteria();
                        issuePolicyLogCriteria.andEqualTo(IssuePolicyLogEntity::getApplicationFormCode, list.get(0).getApplicationFormCode());

                        List<IssuePolicyLogEntity> issuePolicyLogEntities = issuePolicyLogEntityMapper.selectByExample(issuePolicyLogWeekend);
                        if(issuePolicyLogEntities != null && issuePolicyLogEntities.size() > 0){
                            issuePolicyLogEntity.setId(issuePolicyLogEntities.get(0).getId());
                            issuePolicyLogEntity.setTimes(issuePolicyLogEntities.get(0).getTimes());
                            issuePolicyLogEntityMapper.updateByPrimaryKeySelective(issuePolicyLogEntity);
                        }else{
                            issuePolicyLogEntity.setTimes(0);
                            issuePolicyLogEntityMapper.insert(issuePolicyLogEntity);
                        }

                        log.info("{} 调用电子保单接口任务 组装报文{}", findCode, param);
                        String elecSeqNo = Long.toString(Math.abs(new Random().nextLong()));
                        //根据ifCode获取电子保单下载接口
                        String policyIfCode = PolicyEnum.getPolicyOrInvoiceByIfCode(ifCode,"POLICY");
                        ResponseEntity<String> elecResp = dexClient.text("edu", policyIfCode, "1.0", elecSeqNo, param);

                        String elecbody = elecResp.getBody();
                        Document elecdoc = DocumentHelper.parseText(elecbody);
                        String elecdata = XmlUtils.getStringValue(rootElement,"data");
                        String fileId = "";
                        if (StringUtils.isBlank(elecdata)) {
                            consumeStatus = "3";
                            log.error("{} 调用电子保单接口任务 返回结果{}", findCode);
                        }else{
                            consumeStatus = "2";
                            fileId = elecdata;
                            // 下载电子保单成功，更新数据库，绑定资源
                            log.info("{} 调用电子保单接口任务 fileId ：{}", findCode, fileId);
                        }
                        issuePolicyLogEntity.setStatus(consumeStatus);
                        bindingResources(findCode,list.get(0).getApplicationFormCode(), fileId, issuePolicyLogEntity);
                    }
                }else{
                    PayUrlInfoEntity entity = new PayUrlInfoEntity();
                    entity.setPayStatus(true);
                    entity.setPayMessage(responseMessage);
                    entity.setBusinessNo(bussinessNo);
                    entity.setCpcPayTime(cpcPayTime);
                    entity.setUpdateTime(DateUtils.getCurrentTime());
                    entity.setIssueStatus("1");//未出单

                    Weekend<PayUrlInfoEntity> weekend = Weekend.of(PayUrlInfoEntity.class);
                    WeekendCriteria<PayUrlInfoEntity,Object> criteria = weekend.weekendCriteria();
                    criteria.andEqualTo(PayUrlInfoEntity::getCpcNoticeNo, cpcNoticeNo);
                    payUrlInfoMapper.updateByExampleSelective(entity, weekend);

                    log.info("{} 支付成功 但 未返回保单号", findCode);
                }

                // 更新t_pay_out表的支付状态 status = '2'
                Weekend<PayUrlInfoEntity> weekend = Weekend.of(PayUrlInfoEntity.class);
                WeekendCriteria<PayUrlInfoEntity,Object> criteria = weekend.weekendCriteria();
                criteria.andEqualTo(PayUrlInfoEntity::getCpcNoticeNo, cpcNoticeNo);

                // 查询payUrlInfo记录
                List<PayUrlInfoEntity> list = payUrlInfoMapper.selectByExample(weekend);

                if(list != null && list.size() > 0){
                    payOutService.updatePayStatus(list.get(0).getApplicationFormCode(), PayOutStatusEnum.SUCCESS);
                    log.info("{} 支付成功 更新t_pay_out状态完成", findCode);
                }
            }else{
                PayUrlInfoEntity entity = new PayUrlInfoEntity();
                entity.setPayStatus(false);
                entity.setPayMessage(responseMessage);
                entity.setBusinessNo(bussinessNo);
                entity.setCpcPayTime(cpcPayTime);
                entity.setUpdateTime(DateUtils.getCurrentTime());
                entity.setIssueStatus("3");//出单失败

                Weekend<PayUrlInfoEntity> weekend = Weekend.of(PayUrlInfoEntity.class);
                WeekendCriteria<PayUrlInfoEntity,Object> criteria = weekend.weekendCriteria();
                criteria.andEqualTo(PayUrlInfoEntity::getCpcNoticeNo, cpcNoticeNo);
                payUrlInfoMapper.updateByExampleSelective(entity, weekend);

                log.info("{} 支付失败", findCode);
            }
            return true;
        }catch (Exception e){
            e.printStackTrace();
            log.info("{} 处理异常", findCode, e);
            return false;
        }
    }

    /*
     * 解析返回响应报文xml
     * @param document 文档对象
     * @return 返回dom元素
     */
    public Element getRespPacket(Element rootElement) {
        Element respPacket = rootElement.element("respPacket");
        Element element = null;
        if (respPacket != null) {
            try {
                element = DocumentHelper.parseText(respPacket.getText()).getRootElement();
            } catch (DocumentException e) {
                e.printStackTrace();
                log.error("xml转义失败，生成xml错误", e);
            }
        }
        return element;
    }

    /*
     * 解析返回请求报文xml
     * @param document 文档对象
     * @return 返回dom元素
     */
    public Element getReqPacket(Element rootElement) {
        Element respPacket = rootElement.element("reqPacket");
        Element element = null;
        if (respPacket != null) {
            try {
                element = DocumentHelper.parseText(respPacket.getText()).getRootElement();
            } catch (DocumentException e) {
                e.printStackTrace();
                log.error("xml转义失败，生成xml错误", e);
            }
        }
        return element;
    }

    /*
     * 绑定资源，更新下载状态
     * @param applicationFormCode 投保单号
     * @param fileId             文件id
     */
    private void bindingResources(String findCode, String applicationFormCode, String fileId,IssuePolicyLogEntity issuePolicyLogEntity) throws Exception {

        String consumeStatus = issuePolicyLogEntity.getStatus();
        log.info("{} 绑定电子保单 开始 applicationFormCode:{},fileId:{},consumeStatus:{}",findCode,applicationFormCode,fileId,consumeStatus);

        if ("3".equals(consumeStatus)) {
            issuePolicyLogEntity.setTimes(1);
            issuePolicyLogEntity.setEPolicyId(fileId);
            issuePolicyLogEntity.setStatus("3");
            issuePolicyLogEntityMapper.updateByPrimaryKeySelective(issuePolicyLogEntity);
        } else {

            ResBindQo resBindQo = new ResBindQo();
            resBindQo.setApplicationFormCode(applicationFormCode);
            ResBindDetailQo resBindDetailQo = new ResBindDetailQo();
            resBindDetailQo.setBizCodeType("01");
            resBindDetailQo.setResCode("A002");
            resBindDetailQo.setResId(fileId);
            resBindDetailQo.setResName("电子保单、保单影印件");
            List<ResBindDetailQo> list = new ArrayList<>();
            list.add(resBindDetailQo);
            resBindQo.setDetailList(list);
            ResponseEntity<GenericListResponse<Map<String, String>>> genericListResponseResponseEntity = null;
            try {
                String s = JsonUtils.toJson(resBindQo);
                log.info("{} 调用绑定资源接口开始 投保单号:{},入参:{} ", findCode, applicationFormCode, s);
                genericListResponseResponseEntity = insClient.bindResources(resBindQo);
                GenericListResponse<Map<String, String>> body = genericListResponseResponseEntity.getBody();
                String code = body.getCode();
                if (!"0000".equals(code)) {
                    log.info("{} 绑定电子保单 失败 投保单号:{},code:{},msg:{}", findCode, applicationFormCode, body.getCode(), body.getMsg());

                    issuePolicyLogEntity.setTimes(1);
                    issuePolicyLogEntity.setEPolicyId(fileId);
                    issuePolicyLogEntity.setStatus("3");
                    issuePolicyLogEntityMapper.updateByPrimaryKeySelective(issuePolicyLogEntity);

                } else {
                    log.info("{} 绑定电子保单 成功 投保单号:{}, code:{},msg:{}", findCode, applicationFormCode, body.getCode(), body.getMsg());

                    issuePolicyLogEntity.setTimes(1);
                    issuePolicyLogEntity.setEPolicyId(fileId);
                    issuePolicyLogEntity.setStatus("2");
                    issuePolicyLogEntityMapper.updateByPrimaryKeySelective(issuePolicyLogEntity);
                }
            } catch (Exception e) {
                e.printStackTrace();
                log.info("{} 绑定电子保单 异常 {}", findCode, e);

                issuePolicyLogEntity.setTimes(1);
                issuePolicyLogEntity.setEPolicyId(fileId);
                issuePolicyLogEntity.setStatus("3");
                issuePolicyLogEntityMapper.updateByPrimaryKeySelective(issuePolicyLogEntity);
            }
        }
    }
}
